#include "ml307_api.h"
#include "ml307_board.h"

#if (_NETWOK_MODLE_TYPE_ == _ML307R_MODLE_) && (_NETWOK_FUNCTION_ENABLE_)

/**
 * @brief 解析推送消息 URC 事件
 *
 * @param pDataIn         - 待验证的数据
 * @param pDataOut        - 推送原数据
 * @param pSizeOut        - 推送数据长度
 * @return Ml307UrcType_t - 事件类型
 */
static Ml307UrcType_t Ml307Ml307ParsingPublishMessage(const void *pDataIn, uint8_t *pDataOut, uint16_t *pSizeOut);

static Ml307UrcType_t Ml307Ml307ParsingPublishMessage(const void *pDataIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  char *pParsingMessage = (char *)pDataIn;

  if (pParsingMessage != NULL)
  {
    if (strstr(pParsingMessage, "+MQTTURC") != NULL)
    {
      if (Ml307ParsingPublishMessage(pParsingMessage, pDataOut, pSizeOut) == true)
        return MQTT_URC_PUBLISH;
    }
  }

  return MQTT_URC_NO_FIND;
}

bool Ml307BuildCommectTestMessage(void *pDataOut, uint16_t *pSizeOut)
{
  uint16_t MessageSize = 0;
  char *MessagePacket = (char *)pDataOut;

  if ((pDataOut != NULL) && (pSizeOut != NULL))
  {
    MessagePacket[MessageSize++] = 'A';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = '\r';
    MessagePacket[MessageSize++] = '\n';

    *pSizeOut = MessageSize;
    return true;
  }

  return false;
}

bool ML307BuildCloseCommandReturnMessage(void *pDataOut, uint16_t *pSizeOut)
{
  uint16_t MessageSize = 0;
  char *MessagePacket = (char *)pDataOut;

  if ((pDataOut != NULL) && (pSizeOut != NULL))
  {
    MessagePacket[MessageSize++] = 'A';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = 'E';
    MessagePacket[MessageSize++] = '0';
    MessagePacket[MessageSize++] = '\r';
    MessagePacket[MessageSize++] = '\n';

    *pSizeOut = MessageSize;
    return true;
  }

  return false;
}

bool Ml307BuildGetFirmwareVersionMessage(void *pDataOut, uint16_t *pSizeOut)
{
  uint16_t MessageSize = 0;
  char *MessagePacket = (char *)pDataOut;

  if ((pDataOut != NULL) && (pSizeOut != NULL))
  {
    MessagePacket[MessageSize++] = 'A';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = '+';
    MessagePacket[MessageSize++] = 'C';
    MessagePacket[MessageSize++] = 'G';
    MessagePacket[MessageSize++] = 'M';
    MessagePacket[MessageSize++] = 'R';
    MessagePacket[MessageSize++] = '\r';
    MessagePacket[MessageSize++] = '\n';

    *pSizeOut = MessageSize;
    return true;
  }

  return false;
}

bool Ml307BuildQueryModuleManufacturerInformationMessage(void *pDataOut, uint16_t *pSizeOut)
{
  uint16_t MessageSize = 0;
  char *MessagePacket = (char *)pDataOut;

  if ((pDataOut != NULL) && (pSizeOut != NULL))
  {
    MessagePacket[MessageSize++] = 'A';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = '+';
    MessagePacket[MessageSize++] = 'C';
    MessagePacket[MessageSize++] = 'G';
    MessagePacket[MessageSize++] = 'M';
    MessagePacket[MessageSize++] = 'I';
    MessagePacket[MessageSize++] = '\r';
    MessagePacket[MessageSize++] = '\n';

    *pSizeOut = MessageSize;
    return true;
  }

  return false;
}

bool Ml307BuildGetIMEIMessage(void *pDataOut, uint16_t *pSizeOut)
{
  uint16_t MessageSize = 0;
  char *MessagePacket = (char *)pDataOut;

  if ((pDataOut != NULL) && (pSizeOut != NULL))
  {
    MessagePacket[MessageSize++] = 'A';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = '+';
    MessagePacket[MessageSize++] = 'C';
    MessagePacket[MessageSize++] = 'G';
    MessagePacket[MessageSize++] = 'S';
    MessagePacket[MessageSize++] = 'N';
    MessagePacket[MessageSize++] = '=';
    MessagePacket[MessageSize++] = '1';
    MessagePacket[MessageSize++] = '\r';
    MessagePacket[MessageSize++] = '\n';

    *pSizeOut = MessageSize;
    return true;
  }

  return false;
}

bool ML307BuildCheckIfTheSimCardIsRecognizedMessage(void *pDataOut, uint16_t *pSizeOut)
{
  uint16_t MessageSize = 0;
  char *MessagePacket = (char *)pDataOut;

  if ((pDataOut != NULL) && (pSizeOut != NULL))
  {
    MessagePacket[MessageSize++] = 'A';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = '+';
    MessagePacket[MessageSize++] = 'C';
    MessagePacket[MessageSize++] = 'P';
    MessagePacket[MessageSize++] = 'I';
    MessagePacket[MessageSize++] = 'N';
    MessagePacket[MessageSize++] = '?';
    MessagePacket[MessageSize++] = '\r';
    MessagePacket[MessageSize++] = '\n';

    *pSizeOut = MessageSize;
    return true;
  }

  return false;
}

bool Ml307BuildGetIMSIMessage(void *pDataOut, uint16_t *pSizeOut)
{
  uint16_t MessageSize = 0;
  char *MessagePacket = (char *)pDataOut;

  if ((pDataOut != NULL) && (pSizeOut != NULL))
  {
    MessagePacket[MessageSize++] = 'A';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = '+';
    MessagePacket[MessageSize++] = 'C';
    MessagePacket[MessageSize++] = 'I';
    MessagePacket[MessageSize++] = 'M';
    MessagePacket[MessageSize++] = 'I';
    MessagePacket[MessageSize++] = '\r';
    MessagePacket[MessageSize++] = '\n';

    *pSizeOut = MessageSize;
    return true;
  }

  return false;
}

bool Ml307BuildGetIccidMessage(void *pDataOut, uint16_t *pSizeOut)
{
  uint16_t MessageSize = 0;
  char *MessagePacket = (char *)pDataOut;

  if ((pDataOut != NULL) && (pSizeOut != NULL))
  {
    MessagePacket[MessageSize++] = 'A';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = '+';
    MessagePacket[MessageSize++] = 'I';
    MessagePacket[MessageSize++] = 'C';
    MessagePacket[MessageSize++] = 'C';
    MessagePacket[MessageSize++] = 'I';
    MessagePacket[MessageSize++] = 'D';
    MessagePacket[MessageSize++] = '\r';
    MessagePacket[MessageSize++] = '\n';

    *pSizeOut = MessageSize;
    return true;
  }

  return false;
}

bool Ml307BuildCheckSignalStrengthMessage(void *pDataOut, uint16_t *pSizeOut)
{
  uint16_t MessageSize = 0;
  char *MessagePacket = (char *)pDataOut;

  if ((pDataOut != NULL) && (pSizeOut != NULL))
  {
    MessagePacket[MessageSize++] = 'A';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = '+';
    MessagePacket[MessageSize++] = 'C';
    MessagePacket[MessageSize++] = 'S';
    MessagePacket[MessageSize++] = 'Q';
    MessagePacket[MessageSize++] = '\r';
    MessagePacket[MessageSize++] = '\n';

    *pSizeOut = MessageSize;
    return true;
  }

  return false;
}

bool Ml307BuildCheckIfTheNetworkIsRegisteredMessage(void *pDataOut, uint16_t *pSizeOut)
{
  uint16_t MessageSize = 0;
  char *MessagePacket = (char *)pDataOut;

  if ((pDataOut != NULL) && (pSizeOut != NULL))
  {
    MessagePacket[MessageSize++] = 'A';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = '+';
    MessagePacket[MessageSize++] = 'C';
    MessagePacket[MessageSize++] = 'E';
    MessagePacket[MessageSize++] = 'R';
    MessagePacket[MessageSize++] = 'E';
    MessagePacket[MessageSize++] = 'G';
    MessagePacket[MessageSize++] = '?';
    MessagePacket[MessageSize++] = '\r';
    MessagePacket[MessageSize++] = '\n';

    *pSizeOut = MessageSize;
    return true;
  }

  return false;
}

bool Ml307BuildCheckIfTheNtworkIsAttachedMessage(void *pDataOut, uint16_t *pSizeOut)
{
  uint16_t MessageSize = 0;
  char *MessagePacket = (char *)pDataOut;

  if ((pDataOut != NULL) && (pSizeOut != NULL))
  {
    MessagePacket[MessageSize++] = 'A';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = '+';
    MessagePacket[MessageSize++] = 'C';
    MessagePacket[MessageSize++] = 'G';
    MessagePacket[MessageSize++] = 'A';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = '?';
    MessagePacket[MessageSize++] = '\r';
    MessagePacket[MessageSize++] = '\n';

    *pSizeOut = MessageSize;
    return true;
  }

  return false;
}

bool Ml307BuildGetNetworkOperatorMessage(void *pDataOut, uint16_t *pSizeOut)
{
  uint16_t MessageSize = 0;
  char *MessagePacket = (char *)pDataOut;

  if ((pDataOut != NULL) && (pSizeOut != NULL))
  {
    MessagePacket[MessageSize++] = 'A';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = '+';
    MessagePacket[MessageSize++] = 'C';
    MessagePacket[MessageSize++] = 'O';
    MessagePacket[MessageSize++] = 'P';
    MessagePacket[MessageSize++] = 'S';
    MessagePacket[MessageSize++] = '?';
    MessagePacket[MessageSize++] = '\r';
    MessagePacket[MessageSize++] = '\n';

    *pSizeOut = MessageSize;
    return true;
  }

  return false;
}

bool Ml307BuildSelectNetworkOperatorMessage(void *pDataOut, uint16_t *pSizeOut, uint8_t Operator)
{
  uint16_t MessageSize = 0;
  char *MessagePacket = (char *)pDataOut;

  if ((pDataOut != NULL) && (pSizeOut != NULL))
  {
    MessagePacket[MessageSize++] = 'A';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = '+';
    MessagePacket[MessageSize++] = 'C';
    MessagePacket[MessageSize++] = 'O';
    MessagePacket[MessageSize++] = 'P';
    MessagePacket[MessageSize++] = 'S';
    MessagePacket[MessageSize++] = '=';
    sprintf(&MessagePacket[MessageSize], "%d", Operator);
    MessageSize = strlen(MessagePacket);
    MessagePacket[MessageSize++] = '\r';
    MessagePacket[MessageSize++] = '\n';

    *pSizeOut = MessageSize;
    return true;
  }

  return false;
}

bool Ml307BuildDnsConfigurationMessage(void *pDataOut, uint16_t *pSizeOut, const uint8_t *pPreferred, const uint8_t *pAlternate)
{
  uint16_t MessageSize = 0;
  char *MessagePacket = (char *)pDataOut;

  if ((pDataOut != NULL) && (pSizeOut != NULL) && (pPreferred != NULL) && (pAlternate != NULL))
  {
    MessagePacket[MessageSize++] = 'A';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = '+';
    MessagePacket[MessageSize++] = 'M';
    MessagePacket[MessageSize++] = 'D';
    MessagePacket[MessageSize++] = 'N';
    MessagePacket[MessageSize++] = 'S';
    MessagePacket[MessageSize++] = 'C';
    MessagePacket[MessageSize++] = 'F';
    MessagePacket[MessageSize++] = 'G';
    MessagePacket[MessageSize++] = '=';
    MessagePacket[MessageSize++] = '"';
    MessagePacket[MessageSize++] = 'i';
    MessagePacket[MessageSize++] = 'p';
    MessagePacket[MessageSize++] = '"';
    MessagePacket[MessageSize++] = ',';
    MessagePacket[MessageSize++] = '"';
    sprintf(&MessagePacket[MessageSize], "%d.%d.%d.%d", pPreferred[0], pPreferred[1], pPreferred[2], pPreferred[3]);
    MessageSize = strlen(MessagePacket);
    MessagePacket[MessageSize++] = '"';
    MessagePacket[MessageSize++] = ',';
    MessagePacket[MessageSize++] = '"';
    sprintf(&MessagePacket[MessageSize], "%d.%d.%d.%d", pAlternate[0], pAlternate[1], pAlternate[2], pAlternate[3]);
    MessageSize = strlen(MessagePacket);
    MessagePacket[MessageSize++] = '"';
    MessagePacket[MessageSize++] = '\r';
    MessagePacket[MessageSize++] = '\n';

    *pSizeOut = MessageSize;
    return true;
  }

  return false;
}

bool Ml307BuildStartDnsDomainNameResolutionMessage(void *pDataOut, uint16_t *pSizeOut, const char *pDomainNameIn)
{
  uint16_t MessageSize = 0;
  char *MessagePacket = (char *)pDataOut;

  if ((pDataOut != NULL) && (pSizeOut != NULL) && (pDomainNameIn != NULL))
  {
    MessagePacket[MessageSize++] = 'A';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = '+';
    MessagePacket[MessageSize++] = 'M';
    MessagePacket[MessageSize++] = 'D';
    MessagePacket[MessageSize++] = 'N';
    MessagePacket[MessageSize++] = 'S';
    MessagePacket[MessageSize++] = 'G';
    MessagePacket[MessageSize++] = 'I';
    MessagePacket[MessageSize++] = 'P';
    MessagePacket[MessageSize++] = '=';
    MessagePacket[MessageSize++] = '"';
    strcat(&MessagePacket[MessageSize], pDomainNameIn);
    MessageSize = strlen(MessagePacket);
    MessagePacket[MessageSize++] = '"';
    MessagePacket[MessageSize++] = '\r';
    MessagePacket[MessageSize++] = '\n';

    *pSizeOut = MessageSize;
    return true;
  }

  return false;
}

bool Ml307BuildTcpOpenMessage(void *pDataOut, uint16_t *pSizeOut, uint8_t *pIpAddress, uint16_t Port)
{
  uint16_t MessageSize = 0;
  char *MessagePacket = (char *)pDataOut;

  if ((pDataOut != NULL) && (pSizeOut != NULL) && (pIpAddress != NULL))
  {
    MessagePacket[MessageSize++] = 'A';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = '+';
    MessagePacket[MessageSize++] = 'M';
    MessagePacket[MessageSize++] = 'I';
    MessagePacket[MessageSize++] = 'P';
    MessagePacket[MessageSize++] = 'O';
    MessagePacket[MessageSize++] = 'P';
    MessagePacket[MessageSize++] = 'E';
    MessagePacket[MessageSize++] = 'N';
    MessagePacket[MessageSize++] = '=';
    MessagePacket[MessageSize++] = '0';
    MessagePacket[MessageSize++] = ',';
    MessagePacket[MessageSize++] = '"';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = 'C';
    MessagePacket[MessageSize++] = 'P';
    MessagePacket[MessageSize++] = '"';
    MessagePacket[MessageSize++] = ',';
    MessagePacket[MessageSize++] = '"';
    sprintf(&MessagePacket[MessageSize], "%d.%d.%d.%d", pIpAddress[0], pIpAddress[1], pIpAddress[2], pIpAddress[3]);
    MessageSize = strlen(MessagePacket);
    MessagePacket[MessageSize++] = '"';
    MessagePacket[MessageSize++] = ',';
    sprintf(&MessagePacket[MessageSize], "%d", Port);
    MessageSize = strlen(MessagePacket);
    MessagePacket[MessageSize++] = '\r';
    MessagePacket[MessageSize++] = '\n';

    *pSizeOut = MessageSize;
    return true;
  }

  return false;
}

bool Ml307BuildTcpGetConnectStatusMessage(void *pDataOut, uint16_t *pSizeOut)
{
  uint16_t MessageSize = 0;
  char *MessagePacket = (char *)pDataOut;

  if ((pDataOut != NULL) && (pSizeOut != NULL))
  {
    MessagePacket[MessageSize++] = 'A';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = '+';
    MessagePacket[MessageSize++] = 'M';
    MessagePacket[MessageSize++] = 'I';
    MessagePacket[MessageSize++] = 'P';
    MessagePacket[MessageSize++] = 'S';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = 'A';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = 'E';
    MessagePacket[MessageSize++] = '=';
    MessagePacket[MessageSize++] = '0';
    MessagePacket[MessageSize++] = '\r';
    MessagePacket[MessageSize++] = '\n';

    *pSizeOut = MessageSize;
    return true;
  }

  return false;
}

bool Ml307BuildTcpSwitchToTransparentModeMessage(void *pDataOut, uint16_t *pSizeOut)
{
  uint16_t MessageSize = 0;
  char *MessagePacket = (char *)pDataOut;

  if ((pDataOut != NULL) && (pSizeOut != NULL))
  {
    MessagePacket[MessageSize++] = 'A';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = '+';
    MessagePacket[MessageSize++] = 'M';
    MessagePacket[MessageSize++] = 'I';
    MessagePacket[MessageSize++] = 'P';
    MessagePacket[MessageSize++] = 'M';
    MessagePacket[MessageSize++] = 'O';
    MessagePacket[MessageSize++] = 'D';
    MessagePacket[MessageSize++] = 'E';
    MessagePacket[MessageSize++] = '=';
    MessagePacket[MessageSize++] = '0';
    MessagePacket[MessageSize++] = ',';
    MessagePacket[MessageSize++] = '1';
    MessagePacket[MessageSize++] = '\r';
    MessagePacket[MessageSize++] = '\n';

    *pSizeOut = MessageSize;
    return true;
  }

  return false;
}

bool Ml307BuildTcpExitTransparentModeMessage(void *pDataOut, uint16_t *pSizeOut)
{
  uint16_t MessageSize = 0;
  char *MessagePacket = (char *)pDataOut;

  if ((pDataOut != NULL) && (pSizeOut != NULL))
  {
    MessagePacket[MessageSize++] = '+';
    MessagePacket[MessageSize++] = '+';
    MessagePacket[MessageSize++] = '+';
    MessagePacket[MessageSize++] = '\r';
    MessagePacket[MessageSize++] = '\n';

    *pSizeOut = MessageSize;
    return true;
  }

  return false;
}

bool Ml307BuildTcpCloseMessage(void *pDataOut, uint16_t *pSizeOut)
{
  uint16_t MessageSize = 0;
  char *MessagePacket = (char *)pDataOut;

  if ((pDataOut != NULL) && (pSizeOut != NULL))
  {
    MessagePacket[MessageSize++] = 'A';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = '+';
    MessagePacket[MessageSize++] = 'M';
    MessagePacket[MessageSize++] = 'I';
    MessagePacket[MessageSize++] = 'P';
    MessagePacket[MessageSize++] = 'C';
    MessagePacket[MessageSize++] = 'L';
    MessagePacket[MessageSize++] = 'O';
    MessagePacket[MessageSize++] = 'S';
    MessagePacket[MessageSize++] = 'E';
    MessagePacket[MessageSize++] = '=';
    MessagePacket[MessageSize++] = '0';
    MessagePacket[MessageSize++] = '\r';
    MessagePacket[MessageSize++] = '\n';

    *pSizeOut = MessageSize;
    return true;
  }

  return false;
}

bool Ml307BuildMqttDiscMessage(void *pDataOut, uint16_t *pSizeOut, uint8_t Handle)
{
  uint16_t MessageSize = 0;
  char *MessagePacket = (char *)pDataOut;

  if ((pDataOut != NULL) && (pSizeOut != NULL))
  {
    MessagePacket[MessageSize++] = 'A';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = '+';
    MessagePacket[MessageSize++] = 'M';
    MessagePacket[MessageSize++] = 'Q';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = 'D';
    MessagePacket[MessageSize++] = 'I';
    MessagePacket[MessageSize++] = 'S';
    MessagePacket[MessageSize++] = 'C';
    MessagePacket[MessageSize++] = '=';
    sprintf(&MessagePacket[MessageSize], "%d", Handle);
    MessageSize = strlen(MessagePacket);
    MessagePacket[MessageSize++] = '\r';
    MessagePacket[MessageSize++] = '\n';

    *pSizeOut = MessageSize;
    return true;
  }

  return false;
}

bool Ml307BuildMqttConnectMessage(void *pDataOut, uint16_t *pSizeOut, uint8_t Handle, const char *pDomainNameIn, uint16_t Port, const char *pUserNameIn, const char *pPasswordIn)
{
  uint16_t MessageSize = 0;
  char *MessagePacket = (char *)pDataOut;

  if ((pDataOut != NULL) && (pSizeOut != NULL) && (pDomainNameIn != NULL) && (pUserNameIn != NULL) && (pPasswordIn != NULL))
  {
    MessagePacket[MessageSize++] = 'A';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = '+';
    MessagePacket[MessageSize++] = 'M';
    MessagePacket[MessageSize++] = 'Q';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = 'C';
    MessagePacket[MessageSize++] = 'O';
    MessagePacket[MessageSize++] = 'N';
    MessagePacket[MessageSize++] = 'N';
    MessagePacket[MessageSize++] = '=';

    sprintf(&MessagePacket[MessageSize], "%d", Handle);
    MessageSize = strlen(MessagePacket);
    MessagePacket[MessageSize++] = ',';

    MessagePacket[MessageSize++] = '"';
    strcat(MessagePacket, pDomainNameIn);
    MessageSize = strlen(MessagePacket);
    MessagePacket[MessageSize++] = '"';
    MessagePacket[MessageSize++] = ',';

    sprintf(&MessagePacket[MessageSize], "%d", Port);
    MessageSize = strlen(MessagePacket);
    MessagePacket[MessageSize++] = ',';

    MessagePacket[MessageSize++] = '"';
    MessagePacket[MessageSize++] = 'r';
    MessagePacket[MessageSize++] = 'e';
    MessagePacket[MessageSize++] = 'a';
    MessagePacket[MessageSize++] = 'd';
    MessagePacket[MessageSize++] = 'e';
    MessagePacket[MessageSize++] = 'r';
    MessagePacket[MessageSize++] = '"';
    MessagePacket[MessageSize++] = ',';

    MessagePacket[MessageSize++] = '"';
    strcat(MessagePacket, pUserNameIn);
    MessageSize = strlen(MessagePacket);
    MessagePacket[MessageSize++] = '"';
    MessagePacket[MessageSize++] = ',';

    MessagePacket[MessageSize++] = '"';
    strcat(MessagePacket, pPasswordIn);
    MessageSize = strlen(MessagePacket);
    MessagePacket[MessageSize++] = '"';
    MessagePacket[MessageSize++] = '\r';
    MessagePacket[MessageSize++] = '\n';

    *pSizeOut = MessageSize;
    return true;
  }

  return false;
}

bool Ml307BuildMqttSubscribeToTopicsMessage(void *pDataOut, uint16_t *pSizeOut, uint8_t Handle, const char *pToTopicsIn)
{
  uint16_t MessageSize = 0;
  char *MessagePacket = (char *)pDataOut;

  if ((pDataOut != NULL) && (pSizeOut != NULL) && (pToTopicsIn != NULL))
  {
    MessagePacket[MessageSize++] = 'A';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = '+';
    MessagePacket[MessageSize++] = 'M';
    MessagePacket[MessageSize++] = 'Q';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = 'S';
    MessagePacket[MessageSize++] = 'U';
    MessagePacket[MessageSize++] = 'B';
    MessagePacket[MessageSize++] = '=';

    sprintf(&MessagePacket[MessageSize], "%d", Handle);
    MessageSize = strlen(MessagePacket);
    MessagePacket[MessageSize++] = ',';

    MessagePacket[MessageSize++] = '"';
    strcat(MessagePacket, pToTopicsIn);
    MessageSize = strlen(MessagePacket);
    MessagePacket[MessageSize++] = '"';
    MessagePacket[MessageSize++] = ',';

    MessagePacket[MessageSize++] = '1';
    MessagePacket[MessageSize++] = '\r';
    MessagePacket[MessageSize++] = '\n';

    *pSizeOut = MessageSize;
    return true;
  }

  return false;
}

bool Ml307BuildMqttPublishMessage(void *pDataOut, uint16_t *pSizeOut, uint8_t Handle, const char *pToTopicsIn, uint16_t DataSize)
{
  uint16_t MessageSize = 0;
  char *MessagePacket = (char *)pDataOut;

  if ((pDataOut != NULL) && (pSizeOut != NULL) && (pToTopicsIn != NULL))
  {
    MessagePacket[MessageSize++] = 'A';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = '+';
    MessagePacket[MessageSize++] = 'M';
    MessagePacket[MessageSize++] = 'Q';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = 'T';
    MessagePacket[MessageSize++] = 'P';
    MessagePacket[MessageSize++] = 'U';
    MessagePacket[MessageSize++] = 'B';
    MessagePacket[MessageSize++] = '=';

    sprintf(&MessagePacket[MessageSize], "%d", Handle);
    MessageSize = strlen(MessagePacket);
    MessagePacket[MessageSize++] = ',';

    MessagePacket[MessageSize++] = '"';
    strcat(MessagePacket, pToTopicsIn);
    MessageSize = strlen(MessagePacket);
    MessagePacket[MessageSize++] = '"';
    MessagePacket[MessageSize++] = ',';

    MessagePacket[MessageSize++] = '0';
    MessagePacket[MessageSize++] = ',';
    MessagePacket[MessageSize++] = '0';
    MessagePacket[MessageSize++] = ',';
    MessagePacket[MessageSize++] = '0';
    MessagePacket[MessageSize++] = ',';

    sprintf(&MessagePacket[MessageSize], "%d", DataSize);
    MessageSize = strlen(MessagePacket);

    MessagePacket[MessageSize++] = '\r';
    MessagePacket[MessageSize++] = '\n';
    *pSizeOut = MessageSize;
    return true;
  }

  return false;
}

Ml307MessageParsingResult_t Ml307ParsingConnectTestMessage(const void *pDataIn)
{
  char *pParsingMessage = (char *)pDataIn;

  if (pParsingMessage != NULL)
  {
    if (strstr(pParsingMessage, "OK") != NULL)
      return ML307_PARSING_SUCCESS;
  }

  return ML307_PARSING_ERROR;
}

Ml307MessageParsingResult_t Ml307ParsingCloseCommandReturnMessage(const void *pDataIn)
{
  char *pParsingMessage = (char *)pDataIn;

  if (pParsingMessage != NULL)
  {
    if (strstr(pParsingMessage, "OK") != NULL)
      return ML307_PARSING_SUCCESS;
  }

  return ML307_PARSING_ERROR;
}

Ml307MessageParsingResult_t Ml307ParsingGetFirmwareVersionMessage(const void *pDataIn, void *pVersionOut, uint8_t MaxNumberOfVersion)
{
  char *pParsingMessage = (char *)pDataIn, *pKeyword = NULL;

  if (pParsingMessage != NULL)
  {
    if (strstr(pParsingMessage, "OK") != NULL)
    {
      pKeyword = strtok(pParsingMessage, "\r\n");
      if (pKeyword != NULL)
      {
        uint8_t NumberOfVersion = strlen(pKeyword);
        if ((NumberOfVersion > 0) && (NumberOfVersion <= MaxNumberOfVersion))
        {
          if (pVersionOut != NULL)
          {
            memcpy(pVersionOut, pKeyword, NumberOfVersion);
          }
        }

        return ML307_PARSING_SUCCESS;
      }
    }
  }

  return ML307_PARSING_ERROR;
}

Ml307MessageParsingResult_t Ml307ParsingQueryModuleManufacturerInformationMessage(const void *pDataIn, void *pInformationOut, uint8_t MaxNumberOfInformation)
{
  char *pParsingMessage = (char *)pDataIn, *pKeyword = NULL;

  if (pParsingMessage != NULL)
  {
    if (strstr(pParsingMessage, "OK") != NULL)
    {
      pKeyword = strtok(pParsingMessage, "\r\n");
      if (pKeyword != NULL)
      {
        uint8_t NumberOfVersion = strlen(pKeyword);
        if ((NumberOfVersion > 0) && (NumberOfVersion <= MaxNumberOfInformation))
        {
          if (pInformationOut != NULL)
          {
            memcpy(pInformationOut, pKeyword, NumberOfVersion);
          }
        }

        return ML307_PARSING_SUCCESS;
      }
    }
  }

  return ML307_PARSING_ERROR;
}

Ml307MessageParsingResult_t Ml307ParsingGetIMEIMessage(const void *pDataIn, void *pInformationOut, uint8_t MaxNumberOfInformation)
{
  char *pParsingMessage = (char *)pDataIn, *pKeyword = NULL;

  if (pParsingMessage != NULL)
  {
    if (strstr(pParsingMessage, "OK") != NULL)
    {
      pKeyword = strtok(pParsingMessage, " ");

      if (pKeyword != NULL)
      {
        pKeyword = strtok(NULL, "\r\n");

        if (pKeyword != NULL)
        {
          uint8_t NumberOfVersion = strlen(pKeyword);
          if ((NumberOfVersion > 0) && (NumberOfVersion <= MaxNumberOfInformation))
          {
            if (pInformationOut != NULL)
            {
              memcpy(pInformationOut, pKeyword, NumberOfVersion);
            }
          }

          return ML307_PARSING_SUCCESS;
        }
      }
    }
  }

  return ML307_PARSING_ERROR;
}

Ml307MessageParsingResult_t Ml307ParsingCheckIfTheSimCardIsRecognizedMessage(const void *pDataIn)
{
  char *pParsingMessage = (char *)pDataIn, *pKeyword = NULL;

  if (pParsingMessage != NULL)
  {
    if (strstr(pParsingMessage, "OK") != NULL)
    {
      if (strstr(pParsingMessage, "READY") != NULL)
        return ML307_PARSING_SUCCESS;
    }
  }

  return ML307_PARSING_ERROR;
}

Ml307MessageParsingResult_t Ml307ParsingGetIMSIMessage(const void *pDataIn, void *pInformationOut, uint8_t MaxNumberOfInformation)
{
  char *pParsingMessage = (char *)pDataIn, *pKeyword = NULL;

  if (pParsingMessage != NULL)
  {
    if (strstr(pParsingMessage, "OK") != NULL)
    {
      pKeyword = strtok(pParsingMessage, "\r\n");

      if (pKeyword != NULL)
      {
        uint8_t NumberOfVersion = strlen(pKeyword);
        if ((NumberOfVersion > 0) && (NumberOfVersion <= MaxNumberOfInformation))
        {
          if (pInformationOut != NULL)
          {
            memcpy(pInformationOut, pKeyword, NumberOfVersion);
          }
        }

        return ML307_PARSING_SUCCESS;
      }
    }
  }

  return ML307_PARSING_ERROR;
}

Ml307MessageParsingResult_t Ml307ParsingGetIccidMessage(const void *pDataIn, void *pIccidOut, uint8_t MaxNumberOfCardNumber)
{
  char *pParsingMessage = (char *)pDataIn, *pKeyword = NULL;

  if (pParsingMessage != NULL)
  {
    if (strstr(pParsingMessage, "OK") != NULL)
    {
      pKeyword = strtok(pParsingMessage, " ");

      if (pKeyword != NULL)
      {
        pKeyword = strtok(NULL, "\r\n");

        if (pKeyword != NULL)
        {
          uint8_t NumberOfVersion = strlen(pKeyword);
          if ((NumberOfVersion > 0) && (NumberOfVersion <= MaxNumberOfCardNumber))
          {
            if (pIccidOut != NULL)
            {
              memcpy(pIccidOut, pKeyword, NumberOfVersion);
            }
          }

          return ML307_PARSING_SUCCESS;
        }
      }
    }
  }

  return ML307_PARSING_ERROR;
}

Ml307MessageParsingResult_t Ml307ParsingCheckSignalStrengthMessage(const void *pDataIn, uint8_t *pRssiOut)
{
  uint8_t Rssi = 0;
  char *pParsingMessage = (char *)pDataIn, *pKeyword = NULL;

  if (pParsingMessage != NULL)
  {
    if (strstr(pParsingMessage, "OK") != NULL)
    {

      pKeyword = strtok(pParsingMessage, " ");
      if (pKeyword != NULL)
      {
        pKeyword = strtok(NULL, ",");
        if (pKeyword != NULL)
        {
          Rssi = (uint8_t)atoi(pKeyword);
          if (Rssi != 99)
          {
            if (pRssiOut != NULL)
            {
              *pRssiOut = Rssi;
            }

            return ML307_PARSING_SUCCESS;
          }
        }
      }
    }
  }

  return ML307_PARSING_ERROR;
}

Ml307MessageParsingResult_t Ml307ParsingCheckIfTheNetworkIsRegisteredMessage(const void *pDataIn)
{
  uint8_t n = 0, Status = 0;
  char *pParsingMessage = (char *)pDataIn, *pKeyword = NULL;

  if (pParsingMessage != NULL)
  {
    if (strstr(pParsingMessage, "OK") != NULL)
    {
      pKeyword = strtok(pParsingMessage, " ");
      if (pKeyword != NULL)
      {
        pKeyword = strtok(NULL, ",");
        if (pKeyword != NULL)
        {
          n = (uint8_t)atoi(pKeyword);

          pKeyword = strtok(NULL, "\r\n");
          if (pKeyword != NULL)
          {
            Status = (uint8_t)atoi(pKeyword);

            if ((n == 0) && ((Status == 1) || (Status == 5)))
              return ML307_PARSING_SUCCESS;
          }
        }
      }
    }
  }

  return ML307_PARSING_ERROR;
}

Ml307MessageParsingResult_t Ml307ParsingCheckIfTheNtworkIsAttachedMessage(const void *pDataIn)
{
  uint8_t Status = 0;
  char *pParsingMessage = (char *)pDataIn, *pKeyword = NULL;

  if (pParsingMessage != NULL)
  {
    if (strstr(pParsingMessage, "OK") != NULL)
    {
      pKeyword = strtok(pParsingMessage, " ");
      if (pKeyword != NULL)
      {
        pKeyword = strtok(NULL, "\r\n");
        if (pKeyword != NULL)
        {
          Status = (uint8_t)atoi(pKeyword);

          if (Status == 1)
            return ML307_PARSING_SUCCESS;
        }
      }
    }
  }

  return ML307_PARSING_ERROR;
}

Ml307MessageParsingResult_t Ml307ParsingGetNetworkOperatorMessage(const void *pDataIn, void *pInformationOut, uint8_t MaxNumberOfInformation)
{
  return ML307_PARSING_SUCCESS;
}

Ml307MessageParsingResult_t Ml307ParsingSetNetworkOperatorMessage(const void *pDataIn)
{
  return ML307_PARSING_SUCCESS;
}

Ml307MessageParsingResult_t Ml307ParsingDnsConfigurationMessage(const void *pDataIn)
{
  char *pParsingMessage = (char *)pDataIn;

  if (pParsingMessage != NULL)
  {
    if (strstr(pParsingMessage, "OK") != NULL)
      return ML307_PARSING_SUCCESS;
  }

  return ML307_PARSING_ERROR;
}

Ml307MessageParsingResult_t Ml307ParsingStartDnsDomainNameResolutionMessage(const void *pDataIn, uint8_t *pHostIpAddressOut)
{
  char *pParsingMessage = (char *)pDataIn;

  if ((pParsingMessage != NULL) && (pHostIpAddressOut != NULL))
  {
    if (strstr(pParsingMessage, "+MDNSGIP") != NULL)
    {
      const char *pStartString = strstr(pParsingMessage, "\",\"");
      if (pStartString != NULL)
      {
        pStartString += 3;

        const char *pEndString = strchr(pStartString, '"');
        if (pEndString != NULL)
        {
          uint8_t Length = (uint8_t)(pEndString - pStartString);
          if ((Length > 0) && (Length <= 16))
          {
            char IpAddress[16] = {0};

            strncpy(IpAddress, pStartString, pEndString - pStartString);
            IpAddress[pEndString - pStartString] = '\0';

            char *pKeyword = strtok(IpAddress, ".");
            for (uint8_t i = 0; (pKeyword != NULL); i++)
            {
              pHostIpAddressOut[i] = (uint8_t)atoi(pKeyword);
              pKeyword = strtok(NULL, ".");
            }

            return ML307_PARSING_SUCCESS;
          }
        }
      }
    }
    else
      return ML307_PARSING_NO_KEYWORD_FOUND;
  }

  return ML307_PARSING_ERROR;
}

Ml307MessageParsingResult_t Ml307ParsingTcpOpenMessage(const void *pDataIn)
{
  char *pParsingMessage = (char *)pDataIn;

  if (pParsingMessage != NULL)
  {
    if (strstr(pParsingMessage, "+MIPOPEN") != NULL)
    {
      char *pKeyword = strstr(pParsingMessage, ",");
      if (pKeyword != NULL)
      {
        pKeyword++;

        uint8_t Result = (uint8_t)atoi(pKeyword);
        if (Result == 0)
          return ML307_PARSING_SUCCESS;
      }
    }
    else
      return ML307_PARSING_NO_KEYWORD_FOUND;
  }

  return ML307_PARSING_ERROR;
}

Ml307MessageParsingResult_t Ml307ParsingGetTcpConnectStatusMessage(const void *pDataIn)
{
  char *pParsingMessage = (char *)pDataIn;

  if (pParsingMessage != NULL)
  {
    if (strstr(pParsingMessage, "+MIPSTATE") != NULL)
    {
      if (strstr(pParsingMessage, "OK") != NULL)
      {
        if (strstr(pParsingMessage, "CONNECTED") != NULL)
          return ML307_PARSING_SUCCESS;
      }
    }
  }

  return ML307_PARSING_ERROR;
}

Ml307MessageParsingResult_t Ml307ParsingTcpSwitchToTransparentModeMessage(const void *pDataIn)
{
  char *pParsingMessage = (char *)pDataIn;

  if (pParsingMessage != NULL)
  {
    if (strstr(pParsingMessage, "OK") != NULL)
      return ML307_PARSING_SUCCESS;
  }

  return ML307_PARSING_ERROR;
}

Ml307MessageParsingResult_t Ml307ParsingTcpCloseMessage(const void *pDataIn)
{
  char *pParsingMessage = (char *)pDataIn;

  if (pParsingMessage != NULL)
  {
    if (strstr(pParsingMessage, "OK") != NULL)
      return ML307_PARSING_SUCCESS;
  }

  return ML307_PARSING_ERROR;
}

Ml307MessageParsingResult_t Ml307ParsingMqttDiscMessage(const void *pDataIn)
{
  return ML307_PARSING_SUCCESS;
}

Ml307MessageParsingResult_t Ml307ParsingMqttConnectMessage(const void *pDataIn)
{
  return ML307_PARSING_SUCCESS;
}

Ml307MessageParsingResult_t Ml307ParsingMqttSubscribeToTopicsMessage(const void *pDataIn)
{
  char *pParsingMessage = (char *)pDataIn;

  if (pParsingMessage != NULL)
  {
    if (strstr(pParsingMessage, "ERROR") != NULL)
      return ML307_PARSING_ERROR;
  }

  return ML307_PARSING_SUCCESS;
}

Ml307MessageParsingResult_t Ml307DetermineIfItIsMqttUrcEvent(const void *pDataIn)
{
  char *pMessageData = (char *)pDataIn;

  if (pMessageData != NULL)
  {
    if (strstr(pMessageData, "+MQTTURC") != NULL)
      return ML307_PARSING_SUCCESS;
  }

  return ML307_PARSING_ERROR;
}

Ml307MessageParsingResult_t Ml307DetermineIfItIsTcpUrcEvent(const void *pDataIn)
{
  char *pMessageData = (char *)pDataIn;

  if (pMessageData != NULL)
  {
    if (strstr(pMessageData, "+MIPURC") != NULL)
      return ML307_PARSING_SUCCESS;
  }

  return ML307_PARSING_ERROR;
}

Ml307MessageParsingResult_t Ml307DetermineIfTheMessageIsServerPushData(const void *pDataIn)
{
  char *pMessageData = (char *)pDataIn;

  if (pMessageData != NULL)
  {
    if (strstr(pMessageData, "publish") != NULL)
      return ML307_PARSING_SUCCESS;
  }

  return ML307_PARSING_ERROR;
}

Ml307MessageParsingResult_t Ml307DetermineMessageIsInformingNetworkConnectionState(const void *pDataIn, uint8_t *pConnectStatusOut)
{
  Ml307ConnectFormat_t Ml307ConnectFormat = {0};
  char *pKeyword = NULL, *pMessageData = (char *)pDataIn;

  if (pMessageData != NULL)
  {
    if (strstr(pMessageData, "conn") != NULL)
    {
      pKeyword = strtok(pMessageData, " ");
      if (pKeyword != NULL)
      {
        pKeyword = strtok(NULL, ",");
        if (pKeyword != NULL)
        {
          pKeyword = strtok(NULL, ",");
          if (pKeyword != NULL)
          {
            Ml307ConnectFormat.Id = (uint8_t)atoi(pKeyword);

            pKeyword = strtok(NULL, ",");
            if (pKeyword != NULL)
            {
              Ml307ConnectFormat.Status = (uint8_t)atoi(pKeyword);

              if (pConnectStatusOut != NULL)
              {
                *pConnectStatusOut = (Ml307ConnectFormat.Status > ML307_MQTT_SERVER_DISCONNECT) ? ML307_MQTT_CONNECT_FAILED : Ml307ConnectFormat.Status;
              }

              return ML307_PARSING_SUCCESS;
            }
          }
        }
      }
    }
  }

  return ML307_PARSING_ERROR;
}

Ml307MessageParsingResult_t Ml307DetermineMessageIsInformingNetworkDisconnectionState(const void *pDataIn)
{
  char *pMessageData = (char *)pDataIn;

  if (pMessageData != NULL)
  {
    if (strstr(pMessageData, "disconn") != NULL)
      return ML307_PARSING_SUCCESS;
  }

  return ML307_PARSING_ERROR;
}

Ml307MessageParsingResult_t Ml307ParsingPublishMessage(const void *pDataIn, uint8_t *pDataOut, uint16_t *pSizeOut)
{
  MqttPublishFormat_t MqttPublishFormat = {0};
  char *pKeyword = NULL, *pMessageData = (char *)pDataIn;

  if (pMessageData != NULL)
  {
    pKeyword = strtok(pMessageData, " ");
    if (pKeyword != NULL)
    {
      pKeyword = strtok(NULL, ",");
      if (pKeyword != NULL)
      {
        if (strstr(pKeyword, "publish") != NULL)
        {
          pKeyword = strtok(NULL, ",");
          if (pKeyword != NULL)
          {
            MqttPublishFormat.ConnectId = (uint8_t)atoi(pKeyword);

            pKeyword = strtok(NULL, ",");
            if (pKeyword != NULL)
            {
              MqttPublishFormat.Mid = (uint8_t)atoi(pKeyword);

              pKeyword = strtok(NULL, ",");
              if (pKeyword != NULL)
              {
                if (strlen(pKeyword) <= ML307_MQTT_TOPIC_LENGTH)
                {
                  memcpy(MqttPublishFormat.Topic, pKeyword + 1, strlen(pKeyword) - 2);

                  pKeyword = strtok(NULL, ",");
                  if (pKeyword != NULL)
                  {
                    MqttPublishFormat.NumberOfTopic = (uint8_t)atoi(pKeyword);

                    pKeyword = strtok(NULL, ",");
                    if (pKeyword != NULL)
                    {
                      MqttPublishFormat.PayloadSize = (uint16_t)atoi(pKeyword);

                      if (MqttPublishFormat.PayloadSize <= ML307_MAX_RECEIVE_DATA_LENGTH)
                      {
                        pKeyword += strlen(pKeyword) + 1;

                        if ((pDataOut != NULL) && (pSizeOut != NULL))
                        {
                          memcpy(pDataOut, pKeyword, MqttPublishFormat.PayloadSize);
                          *pSizeOut = MqttPublishFormat.PayloadSize;
                        }

                        return ML307_PARSING_SUCCESS;
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }

  return ML307_PARSING_ERROR;
}

#endif
